package com.example.util;


import org.apache.commons.lang3.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class DateUtils {

    public static String PATTERN6 = "yyyyMM";

    public static String PATTERN6_2 = "yyMMdd";

    public static String PATTERN7 = "yyyy-MM";

    public static String PATTERN8 = "yyyyMMdd";

    public static String PATTERN10 = "yyyy-MM-dd";

    public static String PATTERN14 = "yyyyMMddHHmmss";

    public static String PATTERN17 = "yyyyMMddHHmmssSSS";

    public static String PATTERN19 = "yyyy-MM-dd HH:mm:ss";

    public static String NOYEAR10 = "MMddHHmmss";

    public static long nd = 1000 * 24 * 60 * 60; // 一天的毫秒数

    public static long nh = 1000 * 60 * 60; // 一小时的毫秒数

    public static long nm = 1000 * 60; // 一分钟的毫秒数

    public static long ns = 1000; // 一秒钟的毫秒数

    public final static long YEAR = nd * 365;//一年365天的毫秒数

    private static final ThreadLocal<Map<String, SimpleDateFormat>> DATE_FORMAT_HOLDER = new ThreadLocal<Map<String, SimpleDateFormat>>() {

        @Override
        protected Map<String, SimpleDateFormat> initialValue() {

            Map<String, SimpleDateFormat> map = new HashMap<String, SimpleDateFormat>();
            map.put(PATTERN6, new SimpleDateFormat(PATTERN6));
            map.put(PATTERN6_2, new SimpleDateFormat(PATTERN6_2));
            map.put(PATTERN8, new SimpleDateFormat(PATTERN8));
            map.put(PATTERN10, new SimpleDateFormat(PATTERN10));
            map.put(PATTERN14, new SimpleDateFormat(PATTERN14));
            map.put(PATTERN19, new SimpleDateFormat(PATTERN19));
            map.put(NOYEAR10, new SimpleDateFormat(NOYEAR10));
            return map;
        }
    };

    private DateUtils() {

    }

    public static SimpleDateFormat getDateFormat(String pattern) {

        Map<String, SimpleDateFormat> map = DATE_FORMAT_HOLDER.get();
        SimpleDateFormat sdf = map.get(pattern);
        if (sdf == null) {
            sdf = new SimpleDateFormat(pattern);
            map.put(pattern, sdf);
        }
        return sdf;
    }

    public static SimpleDateFormat getDateFormat6() {

        return getDateFormat(PATTERN6);
    }

    public static SimpleDateFormat getDateFormat6_2() {

        return getDateFormat(PATTERN6_2);
    }

    public static SimpleDateFormat getDateFormat7() {

        return getDateFormat(PATTERN7);
    }

    public static SimpleDateFormat getDateFormat8() {

        return getDateFormat(PATTERN8);
    }

    public static SimpleDateFormat getDateFormat10() {

        return getDateFormat(PATTERN10);
    }

    public static SimpleDateFormat getDateFormat17() {

        return getDateFormat(PATTERN17);
    }

    public static SimpleDateFormat getDateFormat14() {

        return getDateFormat(PATTERN14);
    }

    public static SimpleDateFormat getDateFormat19() {

        return getDateFormat(PATTERN19);
    }

    public static SimpleDateFormat getNoYear10() {

        return getDateFormat(NOYEAR10);
    }

    public static String format6(Date date) {

        if (date == null) {
            return "";
        }
        return getDateFormat6().format(date);
    }

    public static String format6_2(Date date) {

        if (date == null) {
            return "";
        }
        return getDateFormat6_2().format(date);
    }

    public static String format7(Date date) {

        if (date == null) {
            return "";
        }
        return getDateFormat7().format(date);
    }

    public static String format8(Date date) {

        if (date == null) {
            return "";
        }
        return getDateFormat8().format(date);
    }

    public static String format10(Date date) {

        if (date == null) {
            return "";
        }
        return getDateFormat10().format(date);
    }

    public static String formatNoYear10(Date date) {

        if (date == null) {
            return "";
        }
        return getNoYear10().format(date);
    }

    public static Date parse10(String dateTime) {

        if (StringUtils.isEmpty(dateTime)) {
            return null;
        }
        try {
            return getDateFormat10().parse(dateTime);
        } catch (ParseException e) {
            return null;
        }
    }

    public static Date parse10_end(String dateTime) {

        if (StringUtils.isEmpty(dateTime)) {
            return null;
        }
        try {
            return add(getDateFormat10().parse(dateTime), Calendar.DATE, 1);
        } catch (ParseException e) {
            return null;
        }
    }

    public static String format14(Date date) {

        if (date == null) {
            return "";
        }
        return getDateFormat14().format(date);
    }

    public static Date parse14(String dateTime) {

        if (StringUtils.isEmpty(dateTime)) {
            return null;
        }
        try {
            return getDateFormat14().parse(dateTime);
        } catch (ParseException e) {
            return null;
        }
    }

    public static String format17(Date date) {

        if (date == null) {
            return "";
        }
        return getDateFormat17().format(date);
    }

    public static String format19(Date date) {

        if (date == null) {
            return "";
        }
        return getDateFormat19().format(date);
    }

    public static Date parse19(String text) {

        if (StringUtils.isEmpty(text)) {
            return null;
        }
        try {
            return getDateFormat19().parse(text);
        } catch (ParseException e) {
            return null;
        }
    }

    public static Date getNextDay(Date date) {

        try {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            date = calendar.getTime();
        } catch (Exception e) {
        }
        return date;
    }

    public static String getWeek(int index) {

        String str[] = { "周日", "周一", "周二", "周三", "周四", "周五", "周六" };
        return str[index];
    }

    public static String getDateDiffString(Date d1, Date d2) {

        Long diff = d1.getTime() - d2.getTime();
        long day = diff / nd;
        long hour = diff % nd / nh;
        long minute = diff % nd % nh / nm;
        long second = diff % nd % nh % nm / ns;
        return "" + day + "天" + hour + "时" + minute + "分" + second + "秒";
    }

    public static Long getDateDiffHour(Date d1, Date d2) {

        if (d1 == null || d2 == null) {
            return -1L;
        }
        Long diff = d1.getTime() - d2.getTime();
        long hour = diff / nh;
        return hour;
    }

    public static Long getDateDiffMin(Date d1, Date d2) {

        if (d1 == null || d2 == null) {
            return -1L;
        }
        Long diff = d1.getTime() - d2.getTime();
        long min = diff / nm;
        return min;
    }

    public static Date date(int year, int month, int day) {

        return date(year, month, day, 0, 0, 0);
    }

    public static Date date(int year, int month, int day, int hour, int minute, int second) {

        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month, day, hour, minute, second);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date add(Date date, int field, int value) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(field, value);
        return calendar.getTime();
    }

    public static Calendar calendar(Date date) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar;
    }

    public static int age(Date dateOfBirth, Date targetDate) {

        Calendar birth = calendar(dateOfBirth);
        Calendar target = calendar(targetDate);
        int age = target.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
        if ((birth.get(Calendar.MONTH) > target.get(Calendar.MONTH)) || (birth.get(Calendar.MONTH) == target.get(Calendar.MONTH) && birth.get(Calendar.DAY_OF_MONTH) > target.get(Calendar.DAY_OF_MONTH))) {
            age--;
        }
        return age;
    }

    public static String getLastMonthFirstDay() {

        Calendar cal = Calendar.getInstance();
        Date date = new Date();
        cal.setTime(date);
        int year = 0;
        int month = cal.get(Calendar.MONTH);
        if (month == 0) {
            year = cal.get(Calendar.YEAR) - 1;
            month = 12;
        } else {
            year = cal.get(Calendar.YEAR);
        }
        String endDay = year + "-" + month + "-01";
        return endDay;
    }

    public static String getLastMonthLastDay() {

        Calendar cal = Calendar.getInstance();
        Date date = new Date();
        cal.setTime(date);
        int year = 0;
        int month = cal.get(Calendar.MONTH);
        int day = getLastMonthDayLenth();
        if (month == 0) {
            year = cal.get(Calendar.YEAR) - 1;
            month = 12;
        } else {
            year = cal.get(Calendar.YEAR);
        }
        String endDay = year + "-" + month + "-" + day;
        return endDay;
    }

    public static int getLastMonthDayLenth() {

        Calendar calendar = new GregorianCalendar();
        Calendar calendar1 = new GregorianCalendar(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) - 1, 1);
        return calendar1.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    public static Integer DayDiff(Date firstDay, Date secondDay) {

        Long day = 60L * 60 * 24;
        Long diff = (firstDay.getTime() - secondDay.getTime()) / 1000;
        Long diffDay = diff / day;
        return diffDay.intValue();
    }

    public static boolean isHoliday(Date date) {

        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            return true;
        }
        return false;
    }

    public static Date overdueTimeCompute(Date deliveryTime, int packageLife, boolean holidaySkip, String festivals) {

        if (!holidaySkip) {
            return add(deliveryTime, Calendar.HOUR_OF_DAY, packageLife);
        }
        Date overdueTime = new Date();
        overdueTime.setTime(deliveryTime.getTime());
        while (packageLife > 0) {
            Calendar c = Calendar.getInstance();
            c.setTimeInMillis(overdueTime.getTime());
            c.add(Calendar.DATE, 1);
            c.set(Calendar.HOUR_OF_DAY, 0);
            c.set(Calendar.MINUTE, 0);
            c.set(Calendar.SECOND, 0);
            long step = Math.min(packageLife * nh, c.getTimeInMillis() - overdueTime.getTime());
            if (!festivals.contains(format10(overdueTime))) {
                packageLife -= step / nh;
            }
            overdueTime.setTime(overdueTime.getTime() + step);
        }
        return overdueTime;
    }

    public static Date getDateEnd(Date date) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }

    public static Date getDateBeing(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Date lastMonthFirstDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime();
    }

    public static Date lastMonthEndDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 0);
        return calendar.getTime();
    }

    /**
     * @Description: 获取月份方法
     * @Author: XDH
     * @Date: 2019/5/9
     */
    public static String getMonth(Calendar calendar) {
        DateFormat bf = new SimpleDateFormat("yyyy-MM");
        return bf.format(calendar.getTime());
    }

    public static String getYesterdayByDate(){
        //实例化当天的日期
        Date today = new Date();
        //用当天的日期减去昨天的日期
        Date yesterdayDate = new Date(today.getTime()-86400000L);
        String yesterday = new SimpleDateFormat("yyyy-MM-dd").format(yesterdayDate);
        return yesterday;
    }
}
